//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V1.0.0
/********************************************************
    说明：
    1、提供DMA实时状态。
    2、由外部配置DMA相关参数。
    3、支持查询DMA传输个数。
    4、支持手动关闭DMA。
    5、由外部提供DMA回调函数。
    6、支持DMA内存拷贝（自动锁定空闲通道，拷贝完后自动释放通道）。
    7、基于stm32f4xx标准库V1.9.0
**********************************************************/

#ifndef __DMA_BSP_H__
#define __DMA_BSP_H__

#include "stm32f4xx.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_dma.h"

#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif

/*DMA信号流枚举*/
typedef enum
{
    Stream_SPI3_RX_1          = DMA1_Stream0_BASE,//SPI3接收
    Stream_I2C1_RX_1          = DMA1_Stream0_BASE,//I2C1接收
    Stream_TIM4_CH1           = DMA1_Stream0_BASE,//定时器4通道1
    Stream_I2S3_EXT_RX_1      = DMA1_Stream0_BASE,//I2S3接收
    Stream_UART5_RX           = DMA1_Stream0_BASE,//串口5接收
    Stream_UART8_TX           = DMA1_Stream0_BASE,//串口8发送
    Stream_TIM5_CH3_TIM5_UP   = DMA1_Stream0_BASE,//定时器5通道3和更新
    Stream_TIM2_UP_TIM2_CH3   = DMA1_Stream1_BASE,//定时器2通道3和更新
    Stream_USART3_RX          = DMA1_Stream1_BASE,//串口3接收
    Stream_UART7_TX           = DMA1_Stream1_BASE,//串口7发送
    Stream_TIM5_CH4_TIM5_TRIG_1 = DMA1_Stream1_BASE,//定时器5通道4和触发
    Stream_TIM6_UP            = DMA1_Stream1_BASE,//定时器6更新
    Stream_SPI3_RX_2          = DMA1_Stream2_BASE,//SPI3接收
    Stream_TIM7_UP_1          = DMA1_Stream2_BASE,//定时器7更新
    Stream_I2S3_EXT_RX_2      = DMA1_Stream2_BASE,//I2S3 EXT接收
    Stream_I2C3_RX            = DMA1_Stream2_BASE,//I2S3接收
    Stream_UART4_RX           = DMA1_Stream2_BASE,//串口4接收
    Stream_TIM3_CH4_TIM3_UP   = DMA1_Stream2_BASE,//定时器3通道4和更新
    Stream_TIM5_CH1           = DMA1_Stream2_BASE,//定时器5通道1
    Stream_I2C2_RX_1          = DMA1_Stream2_BASE,//I2C2接收
    Stream_SPI2_RX            = DMA1_Stream3_BASE,//SPI2接收
    Stream_TIM4_CH2           = DMA1_Stream3_BASE,//定时器4通道2
    Stream_I2S2_EXT_RX        = DMA1_Stream3_BASE,//I2S2 EXT接收
    Stream_USART3_TX_1        = DMA1_Stream3_BASE,//串口3发送
    Stream_UART7_RX           = DMA1_Stream3_BASE,//串口7接收
    Stream_TIM5_TCH4_TIM5_TRIG_2 = DMA1_Stream3_BASE,//定时器5通道4和触发
    Stream_I2C2_RX_2          = DMA1_Stream3_BASE,//I2C2接收
    Stream_SPI2_TX            = DMA1_Stream4_BASE,//SPI2接收
    Stream_TIM7_UP_2          = DMA1_Stream4_BASE,//定时器7更新
    Stream_I2S2_EXT_TX        = DMA1_Stream4_BASE,//I2S2 EXT发送
    Stream_I2C3_TX            = DMA1_Stream4_BASE,//I2C3发送
    Stream_UART4_TX           = DMA1_Stream4_BASE,//串口4发送
    Stream_TIM3_CH1_TIM3_TRIG = DMA1_Stream4_BASE,//定时器3通道1和触发
    Stream_TIM5_CH2           = DMA1_Stream4_BASE,//定时器5通道2
    Stream_USART3_TX_2        = DMA1_Stream4_BASE,//串口3发送
    Stream_SPI3_TX_1          = DMA1_Stream5_BASE,//SPI3发送
    Stream_I2C1_RX_2          = DMA1_Stream5_BASE,//I2C1接收
    Stream_I2S3_EXT_TX        = DMA1_Stream5_BASE,//I2S3 EXT发送
    Stream_TIM2_CH1           = DMA1_Stream5_BASE,//定时器2通道1
    Stream_USART2_RX          = DMA1_Stream5_BASE,//串口2接收
    Stream_TIM3_CH2           = DMA1_Stream5_BASE,//定时器3通道2
    Stream_DAC_CH1            = DMA1_Stream5_BASE,//DAC通道1
    Stream_I2C1_TX_1          = DMA1_Stream6_BASE,//I2C1发送
    Stream_TIM4_UP            = DMA1_Stream6_BASE,//定时器4更新
    Stream_TIM2_CH2_TIM2_CH4  = DMA1_Stream6_BASE,//定时器2通道2和通道4
    Stream_USART2_TX          = DMA1_Stream6_BASE,//串口2发送
    Stream_UART8_RX           = DMA1_Stream6_BASE,//串口8接收
    Stream_TIM5_UP            = DMA1_Stream6_BASE,//定时器5更新
    Stream_DAC_CH2            = DMA1_Stream6_BASE,//DAC通道2
    Stream_SPI3_TX_2          = DMA1_Stream7_BASE,//SPI3发送
    Stream_I2C1_TX_2          = DMA1_Stream7_BASE,//I2C1发送
    Stream_TIM4_CH3           = DMA1_Stream7_BASE,//定时器4通道3
    Stream_TIM2_UP_TIM2_CH4   = DMA1_Stream7_BASE,//定时器2更新和通道4
    Stream_UART5_TX           = DMA1_Stream7_BASE,//串口5发送
    Stream_TIM3_CH3           = DMA1_Stream7_BASE,//定时器3通道3
    Stream_I2C2_TX            = DMA1_Stream7_BASE,//I2C2发送

    Stream_ADC1_1             = DMA2_Stream0_BASE,//ADC1
    Stream_ADC3_1             = DMA2_Stream0_BASE,//ADC3
    Stream_SPI1_RX_1          = DMA2_Stream0_BASE,//SPI1接收
    Stream_SPI4_RX_1          = DMA2_Stream0_BASE,//SPI4接收
    Stream_TIM1_TRIG          = DMA2_Stream0_BASE,//定时器1触发
    Stream_DCMI_1             = DMA2_Stream1_BASE,//DCMI
    Stream_ADC3_2             = DMA2_Stream1_BASE,//ADC3
    Stream_SPI4_TX_1          = DMA2_Stream1_BASE,//SPI4发送
    Stream_USART6_RX_1        = DMA2_Stream1_BASE,//串口6接收
    Stream_TIM1_CH1_1         = DMA2_Stream1_BASE,//定时器1通道1
    Stream_TIM8_UP            = DMA2_Stream1_BASE,//定时器8更新
    Stream_TIM8_CH1_TIM8_CH2_TIM8_CH3 = DMA2_Stream2_BASE,//定时器8通道1和2和3
    Stream_ADC2_1             = DMA2_Stream2_BASE,//ADC2
    Stream_SPI1_RX_2          = DMA2_Stream2_BASE,//SPI1接收
    Stream_USART1_RX_1        = DMA2_Stream2_BASE,//串口1接收
    Stream_USART6_RX_2        = DMA2_Stream2_BASE,//串口6接收
    Stream_TIM1_CH2           = DMA2_Stream2_BASE,//定时器1通道2
    Stream_TIM8_CH1           = DMA2_Stream2_BASE,//定时器8通道1
    Stream_ADC2_2             = DMA2_Stream3_BASE,//ADC2
    Stream_SPI5_RX_1          = DMA2_Stream3_BASE,//SPI5接收
    Stream_SPI1_TX_1          = DMA2_Stream3_BASE,//SPI1发送
    Stream_SDIO_1             = DMA2_Stream3_BASE,//SDIO
    Stream_SPI4_RX_2          = DMA2_Stream3_BASE,//SPI4接收
    Stream_TIM1_CH1_2         = DMA2_Stream3_BASE,//定时器1通道1
    Stream_TIM8_CH2           = DMA2_Stream3_BASE,//定时器8通道2
    Stream_ADC1_2             = DMA2_Stream4_BASE,//ADC1
    Stream_SPI5_TX_1          = DMA2_Stream4_BASE,//SPI5发送
    Stream_SPI4_TX_2          = DMA2_Stream4_BASE,//SPI4发送
    Stream_TIM1_CH4_TIM1_TRIG_TIM1_COM = DMA2_Stream4_BASE,//定时器1通道4和触发和比较
    Stream_TIM8_CH3           = DMA2_Stream4_BASE,//定时器8通道3
    Stream_SPI6_TX            = DMA2_Stream5_BASE,//SPI6发送
    Stream_CRYP_OUT           = DMA2_Stream5_BASE,//CRYP输出
    Stream_SPI1_TX_2          = DMA2_Stream5_BASE,//SPI1发送
    Stream_USART1_RX_2        = DMA2_Stream5_BASE,//串口1接收
    Stream_TIM1_UP            = DMA2_Stream5_BASE,//定时器1更新
    Stream_SPI5_RX_2            = DMA2_Stream5_BASE,//SPI5接收
    Stream_TIM1_CH1_TIM1_CH2_TIM1_CH3 = DMA2_Stream6_BASE,//定时器1通道1和2和3
    Stream_SPI6_RX            = DMA2_Stream6_BASE,//SPI6接收
    Stream_CRYP_IN            = DMA2_Stream6_BASE,//CRYP输入
    Stream_SDIO_2             = DMA2_Stream6_BASE,//SDIO
    Stream_USART6_TX_1        = DMA2_Stream6_BASE,//串口6发送
    Stream_TIM1_CH3           = DMA2_Stream6_BASE,//定时器1通道3
    Stream_SPI5_TX_2          = DMA2_Stream6_BASE,//SPI5发送
    Stream_DCMI_2             = DMA2_Stream7_BASE,//DCMI
    Stream_HASH_IN            = DMA2_Stream7_BASE,//HASH输入
    Stream_USART1_TX          = DMA2_Stream7_BASE,//串口1发送
    Stream_USART6_TX_2        = DMA2_Stream7_BASE,//串口6发送
    Stream_TIM8_CH4_TIM8_TRIG_TIM8_COM = DMA2_Stream7_BASE,//定时器8通道4和触发和比较  
}WHT_DMA_Stream_enum;

/*DMA信号通道枚举*/
typedef enum
{
    Channel_SPI3_RX_1          = DMA_Channel_0,//SPI3接收
    Channel_I2C1_RX_1          = DMA_Channel_1,//I2C1接收
    Channel_TIM4_CH1           = DMA_Channel_2,//定时器4通道1
    Channel_I2S3_EXT_RX_1      = DMA_Channel_3,//I2S3接收
    Channel_UART5_RX           = DMA_Channel_4,//串口5接收
    Channel_UART8_TX           = DMA_Channel_5,//串口8发送
    Channel_TIM5_CH3_TIM5_UP   = DMA_Channel_6,//定时器5通道3和更新
    Channel_TIM2_UP_TIM2_CH3   = DMA_Channel_3,//定时器2通道3和更新
    Channel_USART3_RX          = DMA_Channel_4,//串口3接收
    Channel_UART7_TX           = DMA_Channel_5,//串口7发送
    Channel_TIM5_CH4_TIM5_TRIG_1 = DMA_Channel_6,//定时器5通道4和触发
    Channel_TIM6_UP            = DMA_Channel_7,//定时器6更新
    Channel_SPI3_RX_2          = DMA_Channel_0,//SPI3接收
    Channel_TIM7_UP_1          = DMA_Channel_1,//定时器7更新
    Channel_I2S3_EXT_RX_2      = DMA_Channel_2,//I2S3 EXT接收
    Channel_I2C3_RX            = DMA_Channel_3,//I2S3接收
    Channel_UART4_RX           = DMA_Channel_4,//串口4接收
    Channel_TIM3_CH4_TIM3_UP   = DMA_Channel_5,//定时器3通道4和更新
    Channel_TIM5_CH1           = DMA_Channel_6,//定时器5通道1
    Channel_I2C2_RX_1          = DMA_Channel_7,//I2C2接收
    Channel_SPI2_RX            = DMA_Channel_0,//SPI2接收
    Channel_TIM4_CH2           = DMA_Channel_2,//定时器4通道2
    Channel_I2S2_EXT_RX        = DMA_Channel_3,//I2S2 EXT接收
    Channel_USART3_TX_1        = DMA_Channel_4,//串口3发送
    Channel_UART7_RX           = DMA_Channel_5,//串口7接收
    Channel_TIM5_TCH4_TIM5_TRIG_2 = DMA_Channel_6,//定时器5通道4和触发
    Channel_I2C2_RX_2          = DMA_Channel_7,//I2C2接收
    Channel_SPI2_TX            = DMA_Channel_0,//SPI2接收
    Channel_TIM7_UP_2          = DMA_Channel_1,//定时器7更新
    Channel_I2S2_EXT_TX        = DMA_Channel_2,//I2S2 EXT发送
    Channel_I2C3_TX            = DMA_Channel_3,//I2C3发送
    Channel_UART4_TX           = DMA_Channel_4,//串口4发送
    Channel_TIM3_CH1_TIM3_TRIG = DMA_Channel_5,//定时器3通道1和触发
    Channel_TIM5_CH2           = DMA_Channel_6,//定时器5通道2
    Channel_USART3_TX_2        = DMA_Channel_7,//串口3发送
    Channel_SPI3_TX_1          = DMA_Channel_0,//SPI3发送
    Channel_I2C1_RX_2          = DMA_Channel_1,//I2C1接收
    Channel_I2S3_EXT_TX        = DMA_Channel_2,//I2S3 EXT发送
    Channel_TIM2_CH1           = DMA_Channel_3,//定时器2通道1
    Channel_USART2_RX          = DMA_Channel_4,//串口2接收
    Channel_TIM3_CH2           = DMA_Channel_5,//定时器3通道2
    Channel_DAC_CH1            = DMA_Channel_7,//DAC通道1
    Channel_I2C1_TX_1          = DMA_Channel_1,//I2C1发送
    Channel_TIM4_UP            = DMA_Channel_2,//定时器4更新
    Channel_TIM2_CH2_TIM2_CH4  = DMA_Channel_3,//定时器2通道2和通道4
    Channel_USART2_TX          = DMA_Channel_4,//串口2发送
    Channel_UART8_RX           = DMA_Channel_5,//串口8接收
    Channel_TIM5_UP            = DMA_Channel_6,//定时器5更新
    Channel_DAC_CH2            = DMA_Channel_7,//DAC通道2
    Channel_SPI3_TX_2          = DMA_Channel_0,//SPI3发送
    Channel_I2C1_TX_2          = DMA_Channel_1,//I2C1发送
    Channel_TIM4_CH3           = DMA_Channel_2,//定时器4通道3
    Channel_TIM2_UP_TIM2_CH4   = DMA_Channel_3,//定时器2更新和通道4
    Channel_UART5_TX           = DMA_Channel_4,//串口5发送
    Channel_TIM3_CH3           = DMA_Channel_5,//定时器3通道3
    Channel_I2C2_TX            = DMA_Channel_7,//I2C2发送

    Channel_ADC1_1             = DMA_Channel_0,//ADC1
    Channel_ADC3_1             = DMA_Channel_2,//ADC3
    Channel_SPI1_RX_1          = DMA_Channel_3,//SPI1接收
    Channel_SPI4_RX_1          = DMA_Channel_4,//SPI4接收
    Channel_TIM1_TRIG          = DMA_Channel_6,//定时器1触发
    Channel_DCMI_1             = DMA_Channel_1,//DCMI
    Channel_ADC3_2             = DMA_Channel_2,//ADC3
    Channel_SPI4_TX_1          = DMA_Channel_4,//SPI4发送
    Channel_USART6_RX_1        = DMA_Channel_5,//串口6接收
    Channel_TIM1_CH1_1         = DMA_Channel_6,//定时器1通道1
    Channel_TIM8_UP            = DMA_Channel_7,//定时器8更新
    Channel_TIM8_CH1_TIM8_CH2_TIM8_CH3 = DMA_Channel_0,//定时器8通道1和2和3
    Channel_ADC2_1             = DMA_Channel_1,//ADC2
    Channel_SPI1_RX_2          = DMA_Channel_3,//SPI1接收
    Channel_USART1_RX_1        = DMA_Channel_4,//串口1接收
    Channel_USART6_RX_2        = DMA_Channel_5,//串口6接收
    Channel_TIM1_CH2           = DMA_Channel_6,//定时器1通道2
    Channel_TIM8_CH1           = DMA_Channel_7,//定时器8通道1
    Channel_ADC2_2             = DMA_Channel_1,//ADC2
    Channel_SPI5_RX_1          = DMA_Channel_2,//SPI5接收
    Channel_SPI1_TX_1          = DMA_Channel_3,//SPI1发送
    Channel_SDIO_1             = DMA_Channel_4,//SDIO
    Channel_SPI4_RX_2          = DMA_Channel_5,//SPI4接收
    Channel_TIM1_CH1_2         = DMA_Channel_6,//定时器1通道1
    Channel_TIM8_CH2           = DMA_Channel_7,//定时器8通道2
    Channel_ADC1_2             = DMA_Channel_0,//ADC1
    Channel_SPI5_TX_1          = DMA_Channel_2,//SPI5发送
    Channel_SPI4_TX_2          = DMA_Channel_5,//SPI4发送
    Channel_TIM1_CH4_TIM1_TRIG_TIM1_COM = DMA_Channel_6,//定时器1通道4和触发和比较
    Channel_TIM8_CH3           = DMA_Channel_7,//定时器8通道3
    Channel_SPI6_TX            = DMA_Channel_1,//SPI6发送
    Channel_CRYP_OUT           = DMA_Channel_2,//CRYP输出
    Channel_SPI1_TX_2          = DMA_Channel_3,//SPI1发送
    Channel_USART1_RX_2        = DMA_Channel_4,//串口1接收
    Channel_TIM1_UP            = DMA_Channel_6,//定时器1更新
    Channel_SPI5_RX_2            = DMA_Channel_7,//SPI5接收
    Channel_TIM1_CH1_TIM1_CH2_TIM1_CH3 = DMA_Channel_0,//定时器1通道1和2和3
    Channel_SPI6_RX            = DMA_Channel_1,//SPI6接收
    Channel_CRYP_IN            = DMA_Channel_2,//CRYP输入
    Channel_SDIO_2             = DMA_Channel_4,//SDIO
    Channel_USART6_TX_1        = DMA_Channel_5,//串口6发送
    Channel_TIM1_CH3           = DMA_Channel_6,//定时器1通道3
    Channel_SPI5_TX_2          = DMA_Channel_7,//SPI5发送
    Channel_DCMI_2             = DMA_Channel_1,//DCMI
    Channel_HASH_IN            = DMA_Channel_2,//HASH输入
    Channel_USART1_TX          = DMA_Channel_4,//串口1发送
    Channel_USART6_TX_2        = DMA_Channel_5,//串口6发送
    Channel_TIM8_CH4_TIM8_TRIG_TIM8_COM = DMA_Channel_7,//定时器8通道4和触发和比较  
}WHT_DMA_Channel_enum;

/*DMA状态枚举*/
typedef enum
{
    TRx_TC = 0,//传输完成
    TRx_HT = 1,//传输过半
    TRx_TE = 2,//传输错误
    TRx_TS = 3,//传输开始
}WHT_DMA_State_enum;

/*DMA信息结构体*/
typedef struct
{
    unsigned char Mount_Count;//数据流挂载个数
    FlagStatus BSP_Mutex;     //驱动锁
    WHT_DMA_State_enum State; //传输状态
}WHT_DMA_Info_t;

/*DMA配置结构体*/
typedef struct
{
    WHT_DMA_Stream_enum Stream;     //流
    WHT_DMA_Channel_enum Channel;   //通道
    DMA_InitTypeDef* DMA_InitStruct;//初始化结构体
    void (*IT_Callback)(void);      //回调函数
    volatile WHT_DMA_Info_t* Info;  //信息
    void* Private_Data;             //私有数据
}WHT_DMA_Config_t;

/*DMA回调函数结构体*/
typedef struct
{
    ErrorStatus (*WHT_Register)(const WHT_DMA_Config_t* config);//注册
    void (*WHT_Config)(const WHT_DMA_Config_t* config);         //每个设备可自行配置
    unsigned short (*WHT_Get_Curr_Data_Count)(const WHT_DMA_Config_t* config);//获取当前DMA传输个数
    void (*WHT_Close)(const WHT_DMA_Config_t* config);          //DMA关闭
}WHT_DMA_BSP_t;

/*全局常量*/
extern const WHT_DMA_BSP_t WHT_DMA_BSP;

/*DMA内存拷贝API*/
extern void WHT_DMA_BSP_Memcpy(void* _Dst, void const* _Src, unsigned int _Size);//无法知道传输的状态

#endif // !__DMA_BSP_H__
